home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
Games
/
reve
/
makemove.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-03
|
10KB
|
384 lines
/*LINTLIBRARY*/
/* @(#)makemove.c 1.15 91/11/13
*
* Interface to best computer strategy routines used by Reve.
*
* Copyright (C) 1990, 1991 - Rich Burridge & Yves Gallot.
* All rights reserved.
*
* Permission is granted to copy this source, for redistribution
* in source form only, provided the news headers in "substantially
* unaltered format" are retained, the introductory messages are not
* removed, and no monies are exchanged.
*
* Permission is also granted to copy this source, without the
* news headers, for the purposes of making an executable copy by
* means of compilation, provided that such copy will not be used
* for the purposes of competition in any othello tournaments, without
* prior permission from the authors.
*
* No responsibility is taken for any errors on inaccuracies inherent
* either to the comments or the code of this program, but if reported
* (see README file), then an attempt will be made to fix them.
*/
#include "reve.h"
#include "color.h"
#include <unistd.h>
#include <signal.h>
#include "extern.h"
void
display_time(player, timeleft) /* Display time left in mm:ss format. */
int player, timeleft ;
{
enum panel_type ptype ;
int mins, secs ;
mins = timeleft / 60 ;
secs = timeleft % 60 ;
ptype = (player == BLACK) ? BLACK_CLOCK : WHITE_CLOCK ;
SPRINTF(items[(int) ptype].text, "%1d:%02d", mins, secs) ;
if (DO_CLOCK) draw_clock(W_PANEL, ptype, DO_CLOCK) ;
}
void
domove(pos, mv, nextpos, player)
BOARD *pos, *nextpos ;
int mv, player ;
{
register int i ;
if (pos != nextpos) FOR_BOARD(i) nextpos->square[i] = pos->square[i] ;
s_move = mv ;
s_row = mv >> 3 ;
s_col = mv & 7 ;
s_player = player ;
s_opponent = -player ;
s_flip = TRUE ;
s_pos = nextpos ;
nextpos->square[s_move] = player ;
(void) sandwich(-9) ;
(void) sandwich(-8) ;
(void) sandwich(-7) ;
(void) sandwich(-1) ;
(void) sandwich(1) ;
(void) sandwich(7) ;
(void) sandwich(8) ;
(void) sandwich(9) ;
nextpos->moves_left = (pos->moves_left) - 1 ;
}
FILE *
find_file(filename)
char *filename ;
{
char name[MAXLINE], *paths, *ptr ;
int i = 0 ;
FILE *fp = NULL ;
if ((fp = fopen(filename, "r")) == NULL)
{
paths = getenv("PATH") ;
if ((ptr = paths) && filename[0] != '/')
for (;;)
if (*ptr == ':' || *ptr == 0)
{
if (*ptr == 0) break ;
name[i++] = '/' ;
name[i] = 0 ;
STRCAT(name, edgefile) ;
if ((fp = fopen(name, "r")) != NULL) break ;
if (*ptr == '\0') break ;
ptr++ ;
i = 0 ;
}
else name[i++] = *ptr++ ;
}
return(fp) ;
}
int
fork_child()
{
char *argv[6] ; /* Reve_proc command line arguments. */
int i, tabsiz ;
PIPE(pipe_io[0]) ; /* Setup input pipe. */
PIPE(pipe_io[1]) ; /* Setup output pipe. */
switch (pid = fork())
{
case -1 : CLOSE(pipe_io[0][0]) ;
CLOSE(pipe_io[0][1]) ;
CLOSE(pipe_io[1][0]) ;
CLOSE(pipe_io[1][1]) ;
perror("reve fork failed") ;
exit(1) ;
case 0 : DUP2(pipe_io[0][0], 0) ; /* Child. */
DUP2(pipe_io[1][1], 1) ;
DUP2(pipe_io[1][1], 2) ;
#ifdef NOGETDTAB
#ifdef hpux
tabsiz = _NFILE ;
#else
tabsiz = sysconf(_SC_OPEN_MAX) ;
#endif /*hpux*/
#else
tabsiz = getdtablesize() ;
#endif /*NOGETDTAB*/
for (i = tabsiz; i > 2; i--) CLOSE(i) ;
for (i = 0; i < NSIG; i++) SIGNAL(i, SIG_DFL) ;
i = 0 ;
argv[i++] = "reve_proc" ;
argv[i++] = "-e" ;
argv[i++] = edgefile ;
if (saveres == TRUE) argv[i++] = "-log" ;
if (debug == TRUE) argv[i++] = "-debug" ;
argv[i] = (char *) NULL ;
execvp(reveproc, argv) ;
perror("reve child exec") ;
_exit(-1) ;
default : CLOSE(pipe_io[0][0]) ; /* Parent. */
CLOSE(pipe_io[1][1]) ;
}
return(pid) ;
}
void
init_clocks() /* Setup timer clocks. */
{
items[(int) BLACK_CLOCK].value = timevals[level] * 60 ;
items[(int) WHITE_CLOCK].value = timevals[level] * 60 ;
SPRINTF(items[(int) BLACK_CLOCK].text, "%1d:00", timevals[level]) ;
SPRINTF(items[(int) WHITE_CLOCK].text, "%1d:00", timevals[level]) ;
}
int
legal(mv, player, pos)
BOARD *pos ;
int mv, player ;
{
if (pos->square[mv]) return(FALSE) ; /* Already occupied */
s_move = mv ;
s_row = mv >> 3 ;
s_col = mv & 7 ;
s_player = player ;
s_opponent = -player ;
s_flip = FALSE ;
s_pos = pos ;
return(sandwich(-9) + sandwich(-8) + sandwich(-7) + sandwich(-1) +
sandwich(1) + sandwich(7) + sandwich(8) + sandwich(9)) ;
}
void
read_from_reve(fd)
int fd ;
{
struct reve_out out ;
int reply, sout ;
if (!started) return ;
sout = sizeof(struct reve_out) ;
if ((reply = read(fd, (char *) &out, sout)) > 0)
{
profmax = out.depth ;
if (out.type == M_BEST) show_best(out.move, out.note) ;
else if (out.type == M_MOVE)
{
set_cursor(CANVASCUR) ;
move = out.move ;
note = out.note ;
opponent_move(next_player) ;
}
else if (out.type == M_SUGGESTION)
{
if (legal(out.move, next_player, &board) == 0)
FOR_BOARD(out.move)
if (board.square[out.move] == FREE &&
legal(out.move, next_player, &board)) break ;
do_suggest(next_player, out.move, out.note, IS_ON) ;
if (restore_moves) show_all(IS_ON) ;
sstate = IS_ON ;
suggestion = out.move ;
snote = out.note ;
processing = FALSE ;
}
}
else
{
FPRINTF(stderr, "Couldn't get connection to reve_proc. Exiting.\n",
progname) ;
destroy_reve() ;
}
}
void
reset_clock(player)
int player ;
{
time_t tval ;
start_time = tval = time((time_t *) 0) ; /* Get local time from kernel. */
if (player == BLACK) last_btime = tval ;
else last_wtime = tval ;
}
void
reset_time(timeleft)
time_t timeleft ;
{
struct reve_in in ;
in.type = M_TIME ;
in.timeleft = timeleft ;
WRITE(pipe_io[0][1], (char *) &in, sizeof(struct reve_in)) ;
}
/* Test whether the square move sandwiches a line
* of enemy pieces in the direction [row_inc, col_inc];
* If (s_flip) then update position by capturing such pieces
* Returns the number of pieces captured.
*/
int
sandwich(increment)
register int increment ;
{
register int square, offset ;
int row_offset, col_offset, piece, piece_count ;
int pcount = 0 ;
if ((s_move+increment) < 0 || (s_move+increment) > 63) return(pcount) ;
if (s_pos->square[s_move+increment] != s_opponent) return(pcount) ;
/* Quick test to catch most failures -
* note that the tested square may not even
* be on the board, but the condition is a
* sufficient one for failure.
*/
row_offset = (increment < -1 ? s_row : /* inc -1: -9, -8, -7 */
increment > 1 ? 7-s_row : 8) ; /* inc 1: 7, 8, 9 */
col_offset = (increment & 4 ? s_col : /* inc -1: -9, -1, 7 */
increment & 1 ? 7-s_col : 8) ; /* inc 1: -7, 1, 9 */
offset = (row_offset > col_offset ? col_offset : row_offset) ;
/* offset = shortest distance to an edge in the direction of search */
if (2 > offset) return(pcount) ;
piece_count = 1 ;
square = s_move+increment ;
while (--offset)
{
if (!(piece = s_pos->square[square += increment]))
return(pcount) ; /* If empty square, give up */
if (piece == s_player) break ;
else piece_count++ ; /* Count opponent's pieces encountered */
}
if (!offset) return(pcount) ;
pcount = piece_count ;
if (s_flip)
while (piece_count--)
s_pos->square[square -= increment] = s_player ;
return(pcount) ;
}
void
update_clock(player, doinc) /* Decrement the clock for the current user. */
int player, doinc ;
{
char str[MAXLINE] ;
int diff, n, timeleft ;
time_t cur_time, last_time ;
diff = 0 ;
cur_time = time((time_t *) 0) ;
last_time = (player == BLACK) ? last_btime : last_wtime ;
if (cur_time != last_time) diff = (int) (cur_time - last_time) ;
if (doinc && diff <= 0) diff = 1 ;
else if (diff <= 0) return ;
if (player == BLACK)
{
last_btime = cur_time ;
n = (int) BLACK_CLOCK ;
}
else
{
last_wtime = cur_time ;
n = (int) WHITE_CLOCK ;
}
items[n].value -= diff ;
if (items[n].value < 0) items[n].value = 0 ;
display_time(player, items[n].value) ;
if (DO_CLOCK && items[n].value == 0)
{
cmode = GAME_OVER ;
SPRINTF(str, "Timer expired for %s. ***GAME OVER***",
(player == BLACK) ? bstone_name : wstone_name) ;
message(PANEL_MES, str) ;
beep() ;
}
}
int
valid_move(board, player) /* Check if valid move for this player. */
BOARD *board ;
int player ;
{
int mv ;
int valid ; /* Set if there is a valid move. */
for (mv = 0; mv < 64; mv++)
if (board->square[mv] == FREE)
{
valid = legal(mv, player, board) ;
if (valid > 0) return(TRUE) ;
}
return(FALSE) ;
}
/*ARGSUSED*/
void
write_to_reve(mtype, reve_board, player, level)
enum move_type mtype ;
int *reve_board, player, level ;
{
int i ;
struct reve_in in ;
for (i = 0; i < 64; i++) in.board[i] = reve_board[i] ;
in.player = player ;
in.level = level ;
in.type = mtype ;
processing = TRUE ;
WRITE(pipe_io[0][1], (char *) &in, sizeof(struct reve_in)) ;
}